﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Linq;

using RexToy.Xml;
using RexToy.L10N;
using RexToy.UI.WinForm.Pmlx;
using RexToy.UI.WinForm.ViewModel;

namespace RexToy.UI.WinForm.Controls
{
    public static class ToolStripBuilder
    {
        public static ToolStrip BuildMenu(PmlxNode px)
        {
            if (px.ChildNodes.Count() != 1)
                ThrowHelper.ThrowTemplateError(px);

            var root = px.ChildNodes.First();

            object instance = Activator.CreateInstance(root.MakeType());
            ToolStrip t = instance as ToolStrip;
            if (t == null)
                ThrowHelper.ThrowUnexpectedType(typeof(ToolStrip), instance.GetType());
            ApplyPmlxToTarget(t, root);

            foreach (PmlxNode xChild in root.ChildNodes)
            {
                object child = Activator.CreateInstance(xChild.MakeType());
                ToolStripItem item = child as ToolStripItem;
                if (item == null)
                    ThrowHelper.ThrowUnexpectedType(typeof(ToolStripItem), child.GetType());
                t.Items.Add(item);
                _BuildMenu(item, xChild);
            }

            return t;
        }

        private static void _BuildMenu(ToolStripItem t, PmlxNode x)
        {
            ApplyPmlxToTarget(t, x);
            ToolStripMenuItem menuItem = t as ToolStripMenuItem;
            if (menuItem != null)
            {
                foreach (PmlxNode xChild in x.ChildNodes)
                {
                    object instance = Activator.CreateInstance(xChild.MakeType());
                    ToolStripItem child = instance as ToolStripItem;
                    if (child == null)
                        ThrowHelper.ThrowUnexpectedType(typeof(ToolStripItem), child.GetType());
                    _BuildMenu(child, xChild);
                    menuItem.DropDownItems.Add(child);
                }
            }
        }

        private static void ApplyPmlxToTarget(object target, PmlxNode x)
        {
            StyleCollection styles = x.OwnerDocument.Styles;
            foreach (PmlxNode attr in x.Attributes)
            {
                if (attr.LocalName == PmlxConstant.STYLE)
                {
                    Style style = styles[attr.Value];
                    style.ApplyToInstance(target);
                }
            }

            IReflector r = Reflector.Bind(target);
            foreach (PmlxNode attr in x.Attributes)
            {
                if (attr.LocalName == PmlxConstant.STYLE || attr.LocalName == XAccessor.XMLNS)
                    continue;

                if (attr.LocalName.EndsWith(PmlxConstant.VM_COMMAND) && attr.Value.BracketedBy(StringPair.Delayed_Template_Bracket))
                {
                    IUICommand cmd = new ProxyCommand(x.OwnerDocument.ELEngine, attr.Value);
                    r.SetPropertyValue(attr.LocalName, cmd);
                    continue;
                }

                //Note: If is delay expression, the expression is responsible for l10n. Only deal with static text here.
                if (attr.LocalName.EndsWith(PmlxConstant.TEXT_OF_CONTROL) && (!attr.Value.BracketedBy(StringPair.Delayed_Template_Bracket)))
                {
                    L10NHelper.SetL10nText(attr, r);
                    continue;
                }

                attr.ApplyValue(r);
            }
        }

        public static ToolStrip BuildStatus(PmlxNode px)
        {
            if (px.ChildNodes.Count() != 1)
                ThrowHelper.ThrowTemplateError(px);

            var root = px.ChildNodes.First();

            object instance = Activator.CreateInstance(root.MakeType());
            ToolStrip t = instance as ToolStrip;
            if (t == null)
                ThrowHelper.ThrowUnexpectedType(typeof(ToolStrip), instance.GetType());
            ApplyPmlxToTarget(t, root);

            foreach (PmlxNode xChild in root.ChildNodes)
            {
                object child = Activator.CreateInstance(xChild.MakeType());
                ToolStripItem item = child as ToolStripItem;
                if (item == null)
                    ThrowHelper.ThrowUnexpectedType(typeof(ToolStripItem), child.GetType());
                ApplyPmlxToTarget(item, xChild);
                t.Items.Add(item);
            }

            return t;
        }
    }
}
